import { doApi, getFormValues } from '@/api/basic'
import { template, debounce } from 'lodash-es'
import { isNullOrUnDef } from '@/utils/is'

/**
 * Slider值变化时，等比例同步更改配置的另一个值
 * @param row
 * @param col
 * @param type
 * @param val
 * @returns void
 */
export function doSliderChange(row: any, col: any, type?: string, val?: any) {
  const watch = col?.watch
  // 未配置watch
  if (!watch) {
    return
  }
  const visible = watch?.visible
  // 如果不生效
  if (visible && row[visible.field] != visible.value) {
    return
  }
  const event = watch?.event
  if (!event) {
    return
  }
  const field = event.field
  if (type === 'input') {
    // 拖动值变化时
    const range = col.range
    const result = Math.round((val * col._lockdata[field]) / col._lockdata[col.key])
    if (result < range[0]) {
      row[field] = range[0]
    } else if (result > range[1]) {
      row[field] = range[1]
    } else {
      row[field] = result
    }
  } else if (type === 'change') {
    // 完成拖动时
    const targetValue = row[field]
    const range = col.range
    const result = Math.round((targetValue * col._lockdata[col.key]) / col._lockdata[field])
    if (targetValue === range[0]) {
      if (val < result) {
        row[col.key] = result
      }
    } else if (targetValue === range[1]) {
      if (val > result) {
        row[col.key] = result
      }
    }
  }
}

// 模板字符串
const getStringTempalteData = (tempStr: string, row: any) => {
  try {
    return template(tempStr)(row || {})
  } catch (e) {
    return /\$\{.+\}/.test(tempStr) ? undefined : tempStr
  }
}
// 模板对象
const getObjectTempateData = (obj: any, row: any) => {
  return obj
    ? Object.keys(obj).reduce(
        (t: any, c: any) => {
          if (typeof obj[c] === 'string') {
            t[c] = getStringTempalteData(obj[c], row)
          } else if (obj[c] && typeof obj[c] === 'object') {
            t[c] = getObjectTempateData(obj[c], row)
          } else {
            t[c] = obj[c]
          }
          return t
        },
        Array.isArray(obj) ? [] : {}
      )
    : {}
}

// 执行模板，返回值
export const getTemplateData = (temp: any, row: any) => {
  if (typeof temp === 'string') {
    return getStringTempalteData(temp, row)
  } else if (Array.isArray(temp)) {
    return temp.map((x) =>
      typeof x === 'object' ? getObjectTempateData(x, row) : getStringTempalteData(x, row)
    )
  } else {
    return getObjectTempateData(temp, row)
  }
}

// 根据custom-content 配置生成内容
export const getCustomContent = (content: any, row: any) => {
  const result = getTemplateData(content, row)
  return typeof result === 'string' ? result : JSON.stringify(result)
}

/**
 * 触发更新字段
 * 当字段的值为value时，更新field字段的值为fieldValue
 * 如果配置了fieldElseValue，当字段的值不为value时，更新field字段的值为fieldElseValue
 * 不配置value，每当此字段值变化时就更新field字段的值为fieldValue
 */
export const debounceWatchUpdate = debounce(function (row, colWatch, value) {
  ;[colWatch].flat().forEach((one) => {
    // 未配置value，每次值变化都执行更新
    if (one.value === undefined) {
      row[one.field] = getTemplateData(one.fieldValue, row)
    } else if ([one.value].flat().includes(value)) {
      row[one.field] = getTemplateData(one.fieldValue, row)
    } else if (!isNullOrUnDef(one.fieldElseValue)) {
      row[one.field] = getTemplateData(one.fieldElseValue, row)
    }
  })
}, 300)

/**
 * 配置有editcolumn.changeSelect表格编辑字段时，字段变化时，自动选择行box
 */
export const debounceChangeSelect = debounce(function (row, col, value, $table, callback) {
  if (col?.editcolumn?.changeSelect && value && $table) {
    $table.setCheckboxRow(row, true)
    if (typeof callback === 'function') {
      callback()
    }
  }
}, 500)

/**
 * select值变化时，更改另一个字段的值
 * @param row
 * @param col
 * @param type
 * @param val
 * @returns void
 */
export function doSelectChange(row: any, col: any, _type?: string, val?: any) {
  // 如果配置了source.results，select值改变时改成results，从values里取值
  if (col?.source?.results) {
    const results = col?.source?.results
    const values = col?.values || []
    const data = values.find((x: any) => x[col?.source?.keyField || 'key'] === val)
    Object.keys(results).forEach((field) => {
      try {
        row[field] = template(results[field])(data)
      } catch (e) {}
    })
  }
  // 配置有col.watch的字段，当前字段值变化时触发更新字段
  if (col?.watch) {
    const watch = col?.watch
    // 未配置watch
    if (!watch) {
      return
    }
    const visible = watch?.visible
    // 如果不生效
    if (visible && row[visible.field] != visible.value) {
      return
    }
    // 配置有watch.value和watch.field的逻辑，使用watch编辑时会有bug
    if (watch.value && watch.field) {
      debounceWatchUpdate(row, watch, val)
    }
    const event = watch?.event
    if (!event || !event.field) {
      return
    }
    const field = event.field
    const results = watch?.results || []
    for (let i = 0; i < results.length; i++) {
      // 如果是正则
      if (results[i].type === 'regexp') {
        if (new RegExp(results[i].match).test(val)) {
          row[field] = results[i].value
        }
      } else {
        const matchs = [results[i].match].flat()
        if (matchs.includes(val)) {
          row[field] = results[i].value
        }
      }
    }
  }
}

/**
 * 校验字段是否disabled状态，配置enabled则判断为true的时候不禁用
 * @param row
 * @param col
 * @param grid
 */
export function checkDisabled(row: any, col: any, grid: any) {
  const disabledConfig =
    grid?.props?.enabled || col.enabled || grid?.props?.disabled || col.disabled
  if (typeof disabledConfig === 'object' && disabledConfig !== null) {
    const result = [disabledConfig]
      .flat()
      .some((vis) => Object.keys(vis).every((key) => [vis[key]].flat().includes(row[key])))
    return grid?.props?.enabled || col?.enabled ? !result : result
  }
  return !!disabledConfig
}

/**
 * 日期字符串转Date
 * @param dateString
 * @returns
 */
export function parseDateString(dateString: string, type: string) {
  let date
  // 去掉字符串前后的空白字符
  dateString = dateString.trim()
  if (dateString === 'now()') {
    date = new Date()
  } else if (/^\d+$/.test(dateString) && dateString.length == 13) {
    date = new Date(Number(dateString))
  } else {
    date = new Date(dateString)
  }
  if (type === 'start') {
    return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime()
  } else if (type === 'end') {
    return new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1).getTime()
  } else {
    return date.getTime()
  }
}

/**
 * 校验日期的禁用
 * @param row
 * @param col
 */
export function checkDisabledDate(date: any, row: any, col: any) {
  const time = date.getTime()
  if (col.validDate) {
    const validDates = [col.validDate].flat()
    for (let i = 0; i < validDates.length; i++) {
      const [start, end] = validDates[i]
      if (start && end) {
        try {
          const startDate = parseDateString(template(start)(row || {}), 'start')
          const endDate = parseDateString(template(end)(row || {}), 'emd')
          return startDate > time || !(time < endDate)
        } catch (e) {}
      } else if (!start && end) {
        try {
          const endDate = parseDateString(template(end)(row || {}), 'end')
          return !(time < endDate)
        } catch (e) {}
      } else if (start && !end) {
        try {
          const startDate = parseDateString(template(start)(row || {}), 'start')
          return startDate > time
        } catch (e) {}
      }
    }
    return true
  } else {
    const startDate = parseDateString(`${Date.now()}`, 'start')
    return startDate > time
  }
}
/**
 * 配置source的字段，调用接口查询下拉框
 * @param qs
 * @param col
 * @param form
 * @param grid page配置
 */
export function enumRemoteMethod(qs: string, col: any, form: any, grid?: any) {
  if (col._isLoading) {
    return
  }
  if (col.source) {
    if (col.source?.full_data && col._fullData) {
      col._qs = qs
      return
    }
    const sourceObj = {
      ...(typeof col.source === 'string' ? { source: col.source } : col.source),
      ...(grid?.source && (typeof grid.source === 'string' ? { source: grid.source } : grid.source))
    }
    const source = sourceObj.source
    const conditions: any = {}
    Object.keys(sourceObj.conditions || {}).forEach((key) => {
      try {
        const value = template(sourceObj.conditions[key])(form || {})
        if (!value.includes('${')) {
          conditions[key] = value
        }
      } catch (e) {
        // conditions[key] = sourceObj.conditions[key];
      }
    })
    if (qs) {
      const field = sourceObj.nameField || source.split('.').reverse()[0]
      conditions[field] = qs
    }
    if (!col._query) {
      col._query = { page: 1, size: 20, qs }
    }
    // 如果上一次的查询条件相同，不再重新查询
    if (col._query?.conditions === JSON.stringify(conditions)) {
      return
    } else {
      col._query.page = 1
    }
    col._query.conditions = JSON.stringify(conditions)
    // if (qs) {
    //   const field = sourceObj.nameField || source.split(".").reverse()[0];
    //   conditions[field] = qs;
    //   if (col._query) {
    //     col._query.qs = qs;
    //   } else {
    //     col._query = { qs };
    //   }
    // } else if (col._query) {
    //   col._query.qs = "";
    // } else {
    //   col._query = { qs };
    // }
    col._isLoading = true
    if (sourceObj.url) {
      doApi(
        sourceObj.url,
        {
          ...sourceObj,
          page: col._query.page,
          size: col._query.size,
          conditions,
          url: undefined,
          keyField: undefined,
          nameField: undefined
        },
        sourceObj.method
      )
        .then((res) => {
          console.log(res)
          if (col._query) {
            col._query.count = res.count
          }
          const result = res.data || []
          col._isLoading = undefined
          col.values = result
          if (col.source?.full_data) {
            col._fullData = true
          }
        })
        .finally(() => {
          col._isLoading = false
        })
    } else {
      getFormValues({
        ...sourceObj,
        conditions,
        page: 1,
        size: 20,
        keyField: undefined,
        nameField: undefined
      })
        .then((res: any) => {
          if (col._query) {
            col._query.count = res.count
          }
          const result = res.values || []
          col._isLoading = undefined
          col.values = result
          if (col.source?.full_data) {
            col._fullData = true
          }
        })
        .finally(() => {
          col._isLoading = false
        })
    }
  }
}
/**
 * 配置source的字段，调用接口查询下拉框
 * @param col
 * @param form
 */
export function loadMoreMethod(col: any, form: any, grid: any) {
  if (col._isLoading) {
    return
  }
  if (col.source) {
    if (!col?._query?.count || col?._query?.page * col?._query?.size >= col?._query?.count) {
      return
    }
    col._isLoading = true
    const sourceObj = {
      ...(typeof col.source === 'string' ? { source: col.source } : col.source),
      ...(grid?.source && (typeof grid.source === 'string' ? { source: grid.source } : grid.source))
    }

    const source = sourceObj.source
    const conditions: any = {}
    Object.keys(sourceObj.conditions || {}).forEach((key) => {
      try {
        const value = template(sourceObj.conditions[key])(form || {})
        if (!value.includes('${')) {
          conditions[key] = value
        }
      } catch (e) {
        conditions[key] = sourceObj.conditions[key]
      }
    })
    const query = col._query
    if (query?.qs) {
      const field = sourceObj.nameField || source.split('.').reverse()[0]
      conditions[field] = query?.qs
    }
    if (sourceObj.url) {
      doApi(
        sourceObj.url,
        { ...sourceObj, page: ++query.page, size: col._query.size, conditions },
        sourceObj.method
      )
        .then((res) => {
          console.log(res)
          if (col._query) {
            col._query.count = res.count
          }
          const result = res.data || []
          col._isLoading = undefined
          col.values.push(...result)
        })
        .finally(() => {
          col._isLoading = false
        })
    } else {
      getFormValues({
        ...sourceObj,
        conditions,
        page: ++query.page,
        size: 20,
        keyField: undefined,
        nameField: undefined
      })
        .then((res: any) => {
          query.pageCount = res.count
          const result = res.values || []
          col._isLoading = undefined
          col.values.push(...result)
        })
        .finally(() => {
          col._isLoading = false
        })
    }
  }
}
/**
 * 配置source的字段，调用接口查询下拉框
 * @param col
 * @param form
 */
export function loadOneMethod(col: any, form: any, grid: any) {
  if (col._isLoading) {
    return
  }
  console.log('xxxxxxxxxxx')
  if (col.source) {
    col._isLoading = true
    const sourceObj = {
      ...(typeof col.source === 'string' ? { source: col.source } : col.source),
      ...(grid?.source && (typeof grid.source === 'string' ? { source: grid.source } : grid.source))
    }
    // const source = sourceObj.source
    const conditions: any = {}
    if (sourceObj.keyField && !['list', 'tree-select-multiple'].includes(col.type)) {
      conditions[sourceObj.keyField] = form[col.key]
    } else {
      conditions.ids = [form[col.key]].flat()
    }
    const query = col._query
    getFormValues({ ...sourceObj, conditions, ...query, keyField: undefined, nameField: undefined })
      .then((res: any) => {
        const result = res.values || []
        col._isLoading = undefined
        col.values = result
      })
      .finally(() => {
        col._isLoading = false
      })
  }
}
/**
 * 加载懒加载树的数据
 * @param col
 * @param form
 * @param node
 * @param resolve
 * @returns
 */
export async function loadTreeSelectData(col: any, form: any, node: any, resolve: any) {
  if (node.isLeaf) return resolve([])
  const defaultQuery: any = {
    full_data: true
  }
  if (!node.level && form[col.key]) {
    defaultQuery.ids = [form[col.key]].flat()
  }
  const url = col.props.url
  const params = col.props.params
    ? Object.keys(col.props.params || {}).reduce((t: any, c: any) => {
        try {
          const compiled = template(col.props.params[c])
          t[c] = compiled({ ...form, node: node?.data })
          return t
        } catch (e) {
          return t
        }
      }, defaultQuery)
    : defaultQuery
  doApi(url, params, col.props.method).then((res) => {
    resolve(res.data)
  })
}
/**
 * 初始化tree-select数据
 * @param col
 */
export function initAllTreeSelectData(meta: any = [], form: any) {
  meta
    .filter((col) => ['tree-select', 'tree-select-multiple'].includes(col.type))
    .forEach((col: any) => {
      if (col.isLoading) {
        return
      }
      const defaultQuery: any = {
        full_data: true
      }
      const url = col.props.url
      const params = col.props.params
        ? Object.keys(col.props.params || {}).reduce((t: any, c: any) => {
            try {
              const compiled = template(col.props.params[c])
              t[c] = compiled(form)
              return t
            } catch (e) {
              return t
            }
          }, defaultQuery)
        : defaultQuery
      const newQueryStr = JSON.stringify(params)
      if (newQueryStr != col._query) {
        col._query = JSON.stringify(params)
        doApi(url, params, col.props.method).then((res) => {
          col.values = res.data
        })
      }
    })
}
